package com.sinosoft.vaccinetoai.dao.configure;

import com.zaxxer.hikari.HikariDataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.util.StringUtils;
import tk.mybatis.mapper.autoconfigure.MybatisProperties;
import tk.mybatis.spring.annotation.MapperScan;

import javax.sql.DataSource;
import java.util.Arrays;
import java.util.stream.Stream;

/**
 * 业务数据源配置
 * @author xzh
 * @date 2022-10-24 14:38
 * @since 5.0.0
 */
@Configuration
@EnableConfigurationProperties(MybatisProperties.class)
@EnableTransactionManagement(proxyTargetClass = true)
@MapperScan(basePackages = { "com.sinosoft.vaccinetoai.**.mapper.business","com.sinosoft.vaccinetoai.**.mapper.common.statistics" }, sqlSessionFactoryRef = "businessSqlSessionFactory")
public class BusinessDataSourceConfig {

    private final MybatisProperties properties;

    public BusinessDataSourceConfig(MybatisProperties properties) {
        this.properties = properties;
    }

    @Primary
    @Bean("businessDataSource")
    @ConfigurationProperties(prefix = "app.config.business.data-source-config")
    public HikariDataSource dataSource() {
        HikariDataSource dataSource = DataSourceBuilder.create().type(HikariDataSource.class).build();
        dataSource.setPoolName("BUSINESS-CP");
        return dataSource;
    }

    @Primary
    @Bean("businessTransactionManager")
    public PlatformTransactionManager transactionManager(@Qualifier("businessDataSource") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    @Bean("businessSqlSessionFactory")
    public SqlSessionFactory sqlSessionFactory(@Qualifier("businessDataSource") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(dataSource);
        //开启自动扫描xml 组合式
        Resource[] businessResources = new PathMatchingResourcePatternResolver().getResources("classpath*:mapper/business/*.xml");
        Resource[] commonStatisticsResources = new PathMatchingResourcePatternResolver().getResources("classpath*:mapper/common/statistics/*.xml");
        Resource[] allResources = Stream.concat(Arrays.stream(businessResources), Arrays.stream(commonStatisticsResources))
                .toArray(Resource[]::new);
        bean.setMapperLocations(allResources);
        applyConfiguration(bean);
        if (this.properties.getConfigurationProperties() != null) {
            bean.setConfigurationProperties(this.properties.getConfigurationProperties());
        }
        if (StringUtils.hasLength(this.properties.getTypeAliasesPackage())) {
            bean.setTypeAliasesPackage(this.properties.getTypeAliasesPackage());
        }
        if (this.properties.getTypeAliasesSuperType() != null) {
            bean.setTypeAliasesSuperType(this.properties.getTypeAliasesSuperType());
        }
        if (StringUtils.hasLength(this.properties.getTypeHandlersPackage())) {
            bean.setTypeHandlersPackage(this.properties.getTypeHandlersPackage());
        }

        return bean.getObject();
    }

    private void applyConfiguration(SqlSessionFactoryBean factory) {
        org.apache.ibatis.session.Configuration configuration = this.properties.getConfiguration();
        if (configuration == null && !StringUtils.hasText(this.properties.getConfigLocation())) {
            configuration = new org.apache.ibatis.session.Configuration();
        }
        factory.setConfiguration(configuration);
    }

    @Bean("businessSqlSessionTemplate")
    public SqlSessionTemplate sqlSessionTemplate(@Qualifier("businessSqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
        return new SqlSessionTemplate(sqlSessionFactory);
    }

}
